package com.sparrow.common.aoi.util;

import com.sparrow.common.ai.findpath.PathNode;
import com.sparrow.common.aoi.domain.Area;
import com.sparrow.common.aoi.domain.MapData;
import com.sparrow.common.aoi.impl.ninegrid.AOIMap;
import com.sparrow.common.map.Position;
import com.sparrow.common.map.vector.Vector2;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 地图工具类
 * gridX gridY 表示网格地图的x,y坐标，具体每个格子多少个像素或者unity中的多少m 要和前端约定好。
 *
 */
public class MapUtil {
    /**
     * 九宫格区域的宽有多少个格子
     */
    public static final int AREA_WIDTH = 10;
    /**
     * 九宫格区域的高有多少个格子
     */
    public static final int AREA_HEIGHT = 10;
    /**
     * 地图id = sceneId * base + lineId
     */
    private static final int MAP_ID_BASE = 100;
    /**
     *  每个格子边长 与前端Unity 同步
     */
    public static final float TILE_SIZE = 1.0f;


    public static int toMapId(int sceneId, int lineId) {
        return sceneId * MAP_ID_BASE + lineId;
    }
    /**
     * 根据网格坐标获取区域id
     * @param gridX
     * @param gridY
     * @return
     */
    public static int getAreaByGrid(MapData mapData, int gridX, int gridY) {
        return getAreaId(gridX / mapData.getAreaWidth(), gridY / mapData.getAreaHeight());
    }

    public static int getAreaId(int areaX, int areaY) {
        return areaX * 10000 + areaY;  // Ensure no overflow issue for areaId in future versions.
    }

    /**
     * 根据格子坐标获取九宫格区域
     * @param gridX 格子坐标X
     * @param gridY 格子坐标Y
     * @return 九宫格区域集合
     */
    public static Set<Area> getRoundAreaByGrid(AOIMap map, int gridX, int gridY) {
        return getRoundArea(map, gridX / map.getMapData().getAreaWidth(), gridY / map.getMapData().getAreaHeight());
    }

    /**
     * 获取九宫格区域
     * @param areaX 区域的X坐标
     * @param areaY 区域的Y坐标
     * @return 周围九宫格区域的集合
     */
    public static Set<Area> getRoundArea(AOIMap map, int areaX, int areaY) {
        final int areaRowCount = map.getMapData().getAreaRows();  // 代表区域行数
        final int areaColumnCount = map.getMapData().getAreaCols(); // 代表区域列数

        Set<Area> roundAreas = new HashSet<>();

        // 获取九宫格的边界，避免越界
        int startX = Math.max(0, areaX - 1);
        int endX = Math.min(areaRowCount - 1, areaX + 1);
        int startY = Math.max(0, areaY - 1);
        int endY = Math.min(areaColumnCount - 1, areaY + 1);

        // 遍历周围的九宫格区域
        for (int i = startX; i <= endX; i++) {
            for (int j = startY; j <= endY; j++) {
                Area area = map.getArea(getAreaId(i, j));
                if (area != null) {
                    roundAreas.add(area);
                }
            }
        }
        return roundAreas;
    }

    public static float getDistance(Vector2 v1, Vector2 v2) {
        // 计算向量差
        Vector2 delta = v2.subtract(v1);
        // 计算距离
       return  delta.length();
    }


    public static float getDistance(Position pos1, Position pos2) {
        Vector2 v1 = new Vector2(pos1.getX(), pos1.getZ());
        Vector2 v2 = new Vector2(pos2.getX(), pos2.getZ());
        return getDistance(v1, v2);
    }

    /**
     * 计算欧拉角
     * @param pos1
     * @param pos2
     * @return
     */
    public static int getAngle(Position pos1, Position pos2) {
        // 计算方向向量（朝出生点）
        float dx = pos2.getX() - pos1.getX();
        float dz = pos2.getZ() - pos1.getZ();
        // === 计算欧拉角（yaw） ===
        float yaw = (float) Math.toDegrees(Math.atan2(dz, dx));
        if (yaw < 0) {
            yaw += 360;
        }
        return (int) yaw;
    }

    /** 格子路径 → 世界坐标路径 */
    public static List<Position> toPositionList(List<int[]> path) {
        List<Position> roads = new ArrayList<>(path.size());
        for (int[] node : path) {
            float worldX = node[0] * TILE_SIZE + TILE_SIZE / 2f;
            float worldZ = node[1] * TILE_SIZE + TILE_SIZE / 2f;
            roads.add(new Position(worldX, 0, worldZ));
        }
        return roads;
    }

    /** 世界坐标 → 格子坐标 */
    public static int[] worldToGrid(Position pos) {
        int gridX = (int) (pos.getX() / TILE_SIZE);
        int gridY = (int) (pos.getZ() / TILE_SIZE);
        return new int[]{gridX, gridY};
    }
}
